


#ifndef CATEGORY_H
#define CATEGORY_H



#include <ostream>
#include <list>
#include <string>
#include "subject.h"



// forward decl of expression class
class Expression;



class Category
{
public:
    virtual const std::string &putText( Subject *owner );
    virtual bool personal() const;
    virtual bool empty( Subject *owner = NULL ) =0;
    virtual bool one( Subject *owner = NULL ) =0;
    virtual bool visible() const;
    virtual uint8_t getCount( Subject *owner = NULL ) =0;
    virtual const CollectionSubjects &getSubjects( Subject *owner = NULL ) =0;
    virtual void hasMutated();
    void ref() const { ++m_nRefCount; }
    void deref() const { --m_nRefCount; }
    uint16_t getRefCount() const { return m_nRefCount; }
    virtual void generate( CollectionSubjects &subs, Subject *owner, uint8_t level ) =0;
    
protected:
    Category();
 
    mutable uint16_t m_nRefCount;
    std::string m_Text;
};



class CatCollection : public Category
{
public:
    virtual bool empty( Subject *owner = NULL );
    virtual bool one( Subject *owner = NULL );
    virtual uint8_t getCount( Subject *owner = NULL );
    virtual const CollectionSubjects &getSubjects( Subject *owner = NULL );

protected:
    CollectionSubjects m_Subjects;    
};



class CatColor : public CatCollection
{
protected:
    CatColor( CollectionSubjects &subjs, Color::eColor col );
    
    Color m_Color;
};



class CatAll : public Category
{
public:
    virtual bool empty( Subject *owner = NULL );
    virtual bool one( Subject *owner = NULL );
    virtual uint8_t getCount( Subject *owner = NULL );
    virtual const CollectionSubjects &getSubjects( Subject *owner = NULL );
    
protected:
    CatAll( CollectionSubjects &subjs );

    CollectionSubjects *m_pSubjects;
};



class CatMutable : public CatCollection
{
public:
    virtual void hasMutated();
    virtual bool one( Subject *owner = NULL );
    virtual bool visible() const;
    
protected:
    CatMutable( CollectionSubjects &subs );
    virtual void refill() =0;    
    CollectionSubjects *m_pBaseSubjects;
};



class CatTruth : public CatMutable
{
protected:
    CatTruth( CollectionSubjects &subjs );
    virtual void refill();
};



class CatLying : public CatMutable
{
protected:
    CatLying( CollectionSubjects &subjs );
    virtual void refill();
};



typedef std::list <Category*> CollectionCategories;



#endif
